﻿#define _CRT_SECURE_NO_WARNINGS
#include"string.h"
#include"list.h"


//C++11给出了⼀个引用折叠的规则：右值引用的右值引用折叠成右值引用，所有其他组合均折叠成左值引用。
// 
// 由于引用折叠限定，f1实例化以后x总是⼀个左值引用
template<class T>
void f1(T& x)
{}

// 由于引用折叠限定，f2实例化后可以是左值引用，也可以是右值引用
// 这是一个万能引用，x的引用类型可以根据传参类型T来改变
template<class T>
void f2(T&& x)
{}


void test1() {
	typedef int& lref;
	typedef int&& rref;
	int n = 0;
	lref& r1 = n; // r1 的类型是 int&   解析：int& &r1 -> int&r1  左值引用碰左值引用->左值引用
	lref&& r2 = n; // r2 的类型是 int&  解析：int& &&r2 -> int&r2  左值引用碰右值引用->左值引用
	rref& r3 = n; // r3 的类型是 int&   解析：int&& &r3 -> int&r3  右值引用碰左值引用->左值引用
	rref&& r4 = 1; // r4 的类型是 int&& 解析：int&& &&r4 -> int&&r4  右值引用碰右值引用->右值引用

	//// 没有折叠->实例化为void f1(int& x)
	f1<int>(n);
	//f1<int>(0); // 报错，0是右值
	
	// 折叠->左值引用碰左值引用：实例化为void f1(int& x)
	f1<int&>(n);
	//f1<int&>(0); // 报错 ，0是右值

	// 折叠->右值引用碰左值引用：实例化为void f1(int& x)
	f1<int&&>(n);
	//f1<int&&>(0); // 报错，0是右值

	// 折叠->实例化为void f1(const int& x)  //有const就加const
	f1<const int&>(n);
	f1<const int&>(0);

	// 折叠->实例化为void f1(const int& x)
	f1<const int&&>(n);
	f1<const int&&>(0);


	// 没有折叠->实例化为void f2(int&& x)
	f2<int>(0);
	//f2<int>(n); // 报错,n是左值
	
	// 折叠->实例化为void f2(int& x)
	f2<int&>(n);
	//f2<int&>(0); // 报错

	// 折叠->实例化为void f2(int&& x)
	//f2<int&&>(n); // 报错,n是左值
	f2<int&&>(0);

}


template<class T>
void Function(T&& t)
{
	int a = 0;
	T x = a;
	//x++;
	cout << &a << endl;
	cout << &x << endl << endl;
}
void test2() { //在实际用万能引用的时候，不需要自动实例化T的
	           //类型，会自动推导
			   // 
	// 10是右值，推导出T为int，模板实例化为void Function(int&& t)
	Function(10);
	
	int a;
	// a是左值，推导出T为int&，引⽤折叠，模板实例化为void Function(int& t)
	Function(a);

	// std::move(a)是右值，推导出T为int，模板实例化为void Function(int&& t)
	Function(std::move(a));

	const int b = 8;
	// b是左值，推导出T为const int&，引⽤折叠，模板实例化为void Function(const int&t)
	// 所以Function内部会编译报错，x不能++
	Function(b);


	// std::move(b)右值，推导出T为const int，模板实例化为void Function(const int&&t)
	// 所以Function内部会编译报错，x不能++
	Function(std::move(b));
}




void Fun(int& x) { cout << "左值引⽤" << endl; }
void Fun(int&& x) { cout << "右值引⽤" << endl; }
template<class T>
void Function1(T&& t)
{
	//当T是int时，t是右值引用，但其属性是左值
    //forward<int>(t)之后，t的属性被强制转化为了右值
	//

	//当T是int&时，t是左值引用，其属性是左值
	//forward<int&>(t)之后，t也还为左值
	//

	Fun(forward<T>(t));
}
void test3() { //完美转发

	// 10是右值，推导出T为int，模板实例化为void Function(int&& t)
	Function1(10);

	int a;
	// a是左值，推导出T为int&，引⽤折叠，模板实例化为void Function(int& t)
	Function1(a);
}

void test4() {//完美转发
	lin::string s("111111");
	list<lin::string> lt; //库的list的push_back：
                          //void push_back(const value_type & val);
	                      //void push_back (value_type&& val);
	                     
	lt.push_back(s);          // lin::string 的拷贝构造  
	lt.push_back(move(s));   //  lin::string 的移动构造 ,s已经被交换为NULL

	lt.push_back("122222222"); // lin::string 的有参构造加移动构造
}
void test5() {
	lin::list<lin::string> lt;
	lin::string s("11111111");
	lt.push_back(s);
	lt.push_back(move(s));
	lt.push_back(lin::string("22222222"));
}
int main() {
	//test1();
	//test2();
	test5();
	return 0;

}